package com.bitsfromspace.ubertorrent.peer;

import java.io.IOException;
import java.util.StringTokenizer;

import com.bitsfromspace.ubertorrent.utils.IpUtils;



/**
 * PeerAddress consists of two parts: 
 * <ul>
 * <li>{@link #getIpAddress()} The IP Address </li>
 * <li> {@link #getPort()} The port number </li>
 * </ul>
 * @author: chris.oudeman
 * @since: Jan 6, 2011
 */
public class PeerAddress {

	private final String ipAddress;
	private final int port;

	/**
	 * Creates a new Peer Address. An {@link IOException} is thrown when the IP Address doesn't seem valid,
	 * see {@link IpUtils#validateIp(String)}.
	 * 
	 * @see {@link IpUtils#validateIp(String)}.
	 */
	public PeerAddress(String ipAddress, int port) throws IOException {

		this.ipAddress = ipAddress;
		this.port = port;

		IpUtils.validateIp(ipAddress);
		IpUtils.validatePort(port);

	}

	/**
	 * Returns the IP Address of this {@link PeerAddress}
	 */
	public String getIpAddress() {

		return ipAddress;
	}

	/**
	 * Returns the port number of this {@link PeerAddress}
	 */

	public int getPort() {

		return port;
	}

	/**
	 * Parses this peer address in a 6 byte length byte array.
	 */
	public byte[] toByteString(){
		byte[] bytes = new byte[6];
		StringTokenizer st = new StringTokenizer(ipAddress, ".");
		// IP Address was already validated...
		bytes[0] = (byte) Integer.parseInt(st.nextToken());
		bytes[1] = (byte) Integer.parseInt(st.nextToken());
		bytes[2] = (byte) Integer.parseInt(st.nextToken());
		bytes[3] = (byte) Integer.parseInt(st.nextToken());
		bytes[4] = (byte) (port >>> 8);
		bytes[5] = (byte) port;

		return bytes;
	}

	@Override
	public boolean equals(Object obj) {

		if (obj instanceof PeerAddress) {
			PeerAddress that = (PeerAddress) obj;
			return this.getIpAddress().equals(that.getIpAddress())
					&& this.getPort() == that.getPort();
		}
		return false;
	}

	@Override
	public int hashCode() {

		return 31 * getIpAddress().hashCode() + 31 * getPort();
	}

	@Override
	public String toString() {

		return new StringBuilder("PeerAddress[")
				.append(ipAddress).append(":").append(port).append("]")
				.toString();
	}

	/**
	 * Parses a {@link PeerAddress} from 6 bytes.
	 */
	//FIXME: Remove IOException
	public static PeerAddress createFromByteString(
			byte[] data,
			int offset,
			int length)
																		throws IOException {

		if (length != 6) {
			throw new IOException("Length must be 6 bytes");
		}
		StringBuffer ipBuffer = new StringBuffer();
		for (int ip = 0; ip < 4; ip++) {
			ipBuffer.append(data[offset + ip] & 0xff);
			if (ip != 3) {
				ipBuffer.append(".");
			}
		}

		int port = (data[offset + 4] & 0xff) << 8;
		port += (data[offset + 5] & 0xff);
		return new PeerAddress(ipBuffer.toString(), port);
	}

}


